#include <errno.h>
//
#include <machine/param.h>
#include <sys/ipc.h>
#include <sys/shm.h>
//
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
//
#include <signal.h>
//
#include <sys/uio.h>
#include <unistd.h>
#include <fcntl.h>
//
#include <sys/stat.h>
//
void *shmdata;
//
void closeShm()
{
  shmdt(shmdata);
}
//
void print_usage()
{
  printf("Usage: shm2file shmid offset size fout\n");
}
//
int main(int argc, char *argv[]){
  // 1 shmid

  if(argc<=4){
    print_usage();
    exit(1);
  }

  int shmid=strtol(argv[1],NULL,10);
  size_t offset;
  size_t size;
  const size_t bufsz=1024;
  char fout[bufsz];
  char buf[bufsz];
  char *data;

  shmdata =  shmat ( shmid, ( void * ) 0, 0 );
  if(shmdata==(void *)-1){
    perror("shmat");
    exit(1);
  }

  signal(SIGINT,closeShm);
  signal(SIGTERM,closeShm);

  for(;;){
    if(feof(stdin)) break;
    if(fgets(buf,bufsz,stdin)!=NULL) offset = strtol(buf,NULL,10);
    if(fgets(buf,bufsz,stdin)!=NULL) size = strtol(buf,NULL,10);
    if(fgets(fout,bufsz,stdin)==NULL){
      fprintf(stderr,"cannot get output filename\n");
      continue;
    }

    if(size==0){
      fprintf(stderr,"write size is zero!\n");
      continue;
    }

    data = shmdata + offset;
    
    int d=open(fout,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP);
    if(d==-1){
      perror("open");
      continue;
    }
    
    ssize_t ws=write(d, data, size);
    close(d);
    if(ws==size){
      fprintf(stdout,"ok\n");
    }else{
      fprintf(stdout,"ng\n");
    }

  }

  closeShm();
  exit(0);
}
